/******************************************************************************************
文件名：loice_protocol_version_1.h
作者：狼狼    版本：Loice    创建日期：2021.8.28
文件描述：
    Loice通信协议版本1。
历史修改记录：
1. 2021-8-28:Loice 狼狼
创建。
2. 2022-5-11:Loice 狼狼
代码公开。
******************************************************************************************/
#ifndef LOICE_PROTOCOL_VERSION_1__
#define LOICE_PROTOCOL_VERSION_1__
//+------------------------------------------------------------------------------------------+
//|                                           头文件
//+------------------------------------------------------------------------------------------+
/*|*/#include <stdint.h>
/*|*/#include <internal_cmd.h>
//+------------------------------------------------------------------------------------------+
//|                                         参数宏定义
//+------------------------------------------------------------------------------------------+
//|    ----------------------------------------
//|    指令荷载数据长度限制
//|    ----------------------------------------
/*|*/#define MAX_PAYLOAD_LENGTH 100
/*|*/#define MIN_PAYLOAD_LENGTH 8 // 勿动此值（固定为8，为Loice从设备指令体固定部分长度）
/*|*/#define MIN_PAYLOAD_DATA_LENGTH 8 // 勿动此值（固定为8，为Loice从设备数据体固定部分长度）
//+------------------------------------------------------------------------------------------+
//|                                          数据类型
//+------------------------------------------------------------------------------------------+
/*|*/#pragma pack(4)// 结构体采用4字节对齐方式，数据结构设计也必须完全按照4字节对齐！
//|    ----------------------------------------
//|    消息类型（Message Type）
//|    [说明]消息类型字段为内部使用。
//|    ----------------------------------------
/*|*/typedef enum message_type
/*|*/{
/*|*/    MSG_TYPE_RESERVED     = 0,
//|      ----------------------------------------
//|      指令发送方
//|      ----------------------------------------
/*|*/    CMD_TYPE_NORMAL       = 1,
/*|*/    CMD_TYPE_NOREPLY      = 2,
//|      ----------------------------------------
//|      指令回应
//|      [说明]在以下情况下，接收方将直接丢弃数据
//|            而不产生回应报文：
//|            1. 帧头错误
//|            2. 协议版本不支持
//|            3. 帧头校验失败
//|      ----------------------------------------
/*|*/    CMD_REPLY_OK          = 3,    // 指令被成功接收，即将送往执行
/*|*/    CMD_REPLY_BUSY        = 4,    // 当前暂无法执行该指令，可能上一条指令正在执行或资源被占用
/*|*/    CMD_REPLY_NOT_FOUND   = 5,    // 指令未找到，或不支持/未注册的指令
/*|*/    CMD_REPLY_WRONG_ID    = 6,    // 设备号不匹配，指令将被忽略
/*|*/    CMD_REPLY_OLD_CMD     = 7,    // 过时的指令，收到的指令序号小于上一次接收到的指令序号，指令将被忽略
/*|*/    CMD_REPLY_TOO_LONG    = 8,    // 荷载长度超出接收端承受范围，指令将被忽略
/*|*/    CMD_REPLY_TOO_SHORT   = 9,    // 荷载长度小于合法长度最小值，指令将被忽略
/*|*/    CMD_REPLY_WRONG_CHECK = 10,   // 指令体校验失败
/*|*/    CMD_REPLY_WRONG_ARGS  = 11,   // 指令附加数据非法
/*|*/    CMD_REPLY_CMD_EMPTY   = 12,   // 指令体为空
//|      ----------------------------------------
//|      数据类型
//|      ----------------------------------------
/*|*/    DATA_TYPE_NORMAL      = 13,
/*|*/    DATA_TYPE_NOREPLY     = 14,
/*|*/    DATA_TYPE_REPORT      = 15,
/*|*/    DATA_TYPE_REPORT_NOREPLY = 16,
//|      ----------------------------------------
//|      数据回应
//|      ----------------------------------------
/*|*/    DATA_REPLY_OK          = 17,
/*|*/    DATA_REPLY_WRONG_CHECK = 18,
//|      ----------------------------------------
//|      心跳包相关
//|      ----------------------------------------
/*|*/    KAP_TYPE_NORMAL        = 195, /* 0xC3 */
/*|*/    KAP_TYPE_NOREPLY       = 196, /* 0xC4 */
/*|*/    KAP_REPLY_OK           = 197,
/*|*/    KAP_REPLY_WRONG_ID     = 198, // 设备号不匹配，因此为错误的KAP，消息将被忽略
/*|*/    KAP_REPLY_TOO_LONG     = 199, // 荷载长度超出接收端承受范围，因此为无效的KAP，消息将被忽略
/*|*/}ENUM_MESSAGE_TYPE;
//|
//|    ----------------------------------------
//|    [说明]以下为用于传输指令/数据等荷载的应
//|          用层协议首部。
//|    [重要]当前协议实现中未对时间戳信息做任何
//|          处理，也未基于时间戳信息设计任何动
//|          作，因此该字段应固定为0。
//|    ----------------------------------------
//|    +---------------+---------------+---------------+---------------+
//|    +-----byte 0----|-----byte 1----|-----byte 2----|-----byte 3----+
//|    |7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0|
//|    +---------------+---------------+---------------+---------------+
//|    |                       Head(14-CF-92-5A)                       |
//|    +---------------+---------------+---------------+---------------+
//|    |                       Head(A0-C0-00-FF)                       |
//|    +---------------+---------------+---------------+---------------+
//|    |                Source Device ID(Byte00~Byte03)                |
//|    +---------------+---------------+---------------+---------------+
//|    |                Source Device ID(Byte04~Byte07)                |
//|    +---------------+---------------+---------------+---------------+
//|    |                Source Device ID(Byte08~Byte11)                |
//|    +---------------+---------------+---------------+---------------+
//|    |                Source Device ID(Byte12~Byte15)                |
//|    +---------------+---------------+---------------+---------------+
//|    |                Source Device ID(Byte16~Byte19)                |
//|    +---------------+---------------+---------------+---------------+
//|    |                Source Device ID(Byte20~Byte24)                |
//|    +---------------+---------------+---------------+---------------+
//|    |                      Reserved(00H)(4Bytes)                    |
//|    +---------------+---------------+---------------+---------------+
//|    |              Destination Device ID(Byte00~Byte03)             |
//|    +---------------+---------------+---------------+---------------+
//|    |              Destination Device ID(Byte04~Byte07)             |
//|    +---------------+---------------+---------------+---------------+
//|    |              Destination Device ID(Byte08~Byte11)             |
//|    +---------------+---------------+---------------+---------------+
//|    |              Destination Device ID(Byte12~Byte15)             |
//|    +---------------+---------------+---------------+---------------+
//|    |              Destination Device ID(Byte16~Byte19)             |
//|    +---------------+---------------+---------------+---------------+
//|    |              Destination Device ID(Byte20~Byte24)             |
//|    +---------------+---------------+---------------+---------------+
//|    |                      Reserved(00H)(4Bytes)                    |
//|    +---------------+---------------+---------------+---------------+
//|    | Proto Version |    Reserved   |    Message Sequence Number    |
//|    +---------------+---------------+---------------+---------------+
//|    |                 32-bit Message Timestamp(00H)                 |
//|    +---------------+---------------+---------------+---------------+
//|    |              Reserved For 64-bit Timestamp(00H)               |
//|    +---------------+---------------+---------------+---------------+
//|    |               Payload Length(All Message Body)                |
//|    +---------------+---------------+---------------+---------------+
//|    |          Message Type         |  Message Header Check(16-bit) |
//|    +---------------+---------------+---------------+---------------+
/*|*/  typedef struct loice_protocol_version_1_head
/*|*/  {
/*|*/      uint8_t head[8];
/*|*/      uint8_t source_device_id[24];
/*|*/      uint8_t reserved1[4];
/*|*/      uint8_t destination_device_id[24];
/*|*/      uint8_t reserved2[4];
/*|*/      uint8_t protocol_version;
/*|*/      uint8_t reserved3;
/*|*/      uint16_t msg_seq;
/*|*/      uint32_t msg_timestamp; /* Fixed to 00H */
/*|*/      uint32_t reserved4;
/*|*/      uint32_t payload_length;
/*|*/      uint16_t msg_type;
/*|*/      uint16_t msg_head_check;
/*|*/  }ST_LOICE_PROTO_VER_1_HEAD;
//|
//|    ----------------------------------------
//|    [说明]以下为用于传输指令荷载的应用层协议
//|          指令体。
//|    ----------------------------------------
//|    +---------------+---------------+---------------+---------------+
//|    +-----byte 0----|-----byte 1----|-----byte 2----|-----byte 3----+
//|    |7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0|
//|    +---------------+---------------+---------------+---------------+
//|    |   Command ID  | Reserved(00H) |         Command Value         |
//|    +---------------+---------------+---------------+---------------+
//|    |   Command Body Check(16-bit)  |         Reserved(00H)         |
//|    +---------------+---------------+---------------+---------------+
//|    |                    Variable Length Data                       |
//|    |                              ...                              |
//|    +---------------+---------------+---------------+---------------+
/*|*/  typedef struct loice_protocol_version_1_body_cmd
/*|*/  {
/*|*/      uint8_t cmd_id;
/*|*/      uint8_t reserved1;
/*|*/      uint16_t cmd_value;
/*|*/      uint16_t cmd_body_check;
/*|*/      uint16_t reserved2;
/*|*/      uint8_t *pdata;
/*|*/  }ST_LOICE_PROTO_VER_1_BODY_CMD;
//|
//|    ----------------------------------------
//|    [说明]以下为用于传输数据荷载的应用层协议
//|          消息体。
//|    ----------------------------------------
//|    +---------------+---------------+---------------+---------------+
//|    +-----byte 0----|-----byte 1----|-----byte 2----|-----byte 3----+
//|    |7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0|
//|    +---------------+---------------+---------------+---------------+
//|    |   Data Type   | Reserved(00H) |        Data Type Value        |
//|    +---------------+---------------+---------------+---------------+
//|    |     Data Body Check(16-bit)   | Data Sequence Number(16-bit)  |
//|    +---------------+---------------+---------------+---------------+
//|    |                    Variable Length Data                       |
//|    |                              ...                              |
//|    +---------------+---------------+---------------+---------------+
/*|*/  typedef struct loice_protocol_version_1_body_msg
/*|*/  {
/*|*/      uint8_t data_type;
/*|*/      uint8_t reserved1;
/*|*/      uint16_t data_type_value;
/*|*/      uint16_t msg_body_check;
/*|*/      uint16_t data_seq;
/*|*/      uint8_t *pdata;
/*|*/  }ST_LOICE_PROTO_VER_1_BODY_MSG;
//+------------------------------------------------------------------------------------------+
//|                                          测试用例
//+------------------------------------------------------------------------------------------+
/*
SEQ = 0 ID = 1 Value = 1 KAP
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C3 00 EE 08 
SEQ = 0 ID = 1 Value = 1 错误的设备号
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 35 08 01 00 01 00 02 00 00 00
SEQ = 0 ID = 0 Value = 1 未注册的指令ID
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 34 08 00 00 01 00 01 00 00 00
SEQ = 0 ID = 1 Value = 1 CMD_ACTION_1
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 34 08 01 00 01 00 02 00 00 00
SEQ = 0 ID = 1 Value = 2 未注册的指令值
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 34 08 01 00 02 00 03 00 00 00
SEQ = 0 ID = 1 Value = 1 指令体校验失败
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 34 08 01 00 01 00 03 00 00 00
SEQ = 0 ID = 1 Value = 1 CMD指令无指令体部分（长度为空）
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 2C 08 
SEQ = 0 ID = 1 Value = 1 设备ID错误
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 35 08 01 00 01 00 02 00 00 00

SEQ = 0 ID = 1 Value = 1 指令体缺失（连续3条指令，第一条缺失指令体，后续两条正常）
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 34 08 14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 34 08 01 00 01 00 02 00 00 00 14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 34 08 01 00 01 00 02 00 00 00

SEQ = 0 ID = 1 Value = 1 残缺的指令（连续3条指令，第一条缺失一半的指令内容，后续两条正常）
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 34 08 01 00 01 00 02 00 00 00 14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 34 08 01 00 01 00 02 00 00 00

旧指令测试
SEQ = 1 ID = 1 Value = 1 CMD_ACTION_1
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 35 08 01 00 01 00 02 00 00 00
SEQ = 2 ID = 1 Value = 1 CMD_ACTION_1
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 02 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 36 08 01 00 01 00 02 00 00 00
SEQ = 1 ID = 1 Value = 1 CMD_ACTION_1
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 35 08 01 00 01 00 02 00 00 00
SEQ = 2 ID = 1 Value = 1 CMD_ACTION_1
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 02 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 36 08 01 00 01 00 02 00 00 00
SEQ = 0 ID = 1 Value = 1 CMD_ACTION_1
14 CF 92 5A A0 C0 00 FF 00 00 00 00 11 11 11 11 22 22 22 22 33 33 33 33 44 44 44 44 55 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 01 00 34 08 01 00 01 00 02 00 00 00

*/
//+------------------------------------------------------------------------------------------+

#endif /* End of #define LOICE_PROTOCOL_VERSION_1__ */
